/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package casino;

import java.util.Arrays;

/**
 * Class that populates the empty bins of the specified Roulette wheel with outcomes.
 * 
 * @author amaghfur
 * @since 1.0
 */
public class BinBuilder {
    
    /**
     * Tells this BinBuilder to build bins for the specified roulette game.
     * 
     * @param rouletteGame      the game in question
     */
    public static void buildBins(RouletteGame rouletteGame) {
        generateStraightBets(rouletteGame.getWheel(), rouletteGame.straightBetOdds);
        generateSplitBets(rouletteGame.getWheel(), rouletteGame.splitBetOdds);
        generateStreetBets(rouletteGame.getWheel(), rouletteGame.streetBetOdds);
        generateCornerBets(rouletteGame.getWheel(), rouletteGame.cornerBetOdds);
        generateLineBets(rouletteGame.getWheel(), rouletteGame.lineBetOdds);
        generateDozenBets(rouletteGame.getWheel(), rouletteGame.dozenBetOdds);
        generateColumnBets(rouletteGame.getWheel(), rouletteGame.columnBetOdds);
        generateEvenMoneyBets(rouletteGame.getWheel(), rouletteGame.evenMoneyBetOdds);
        generateFiverBets(rouletteGame.getWheel(), rouletteGame.fiverBetOdds);
    }
    
    /**
     * Adds all the outcomes that are straight bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateStraightBets(Wheel wheel, int betOdds) {
        // build straight bets from 1 to 36
        for(int cnt = 1; cnt < 37; cnt++){
            wheel.addOutcome(cnt,OutcomeFactory.getOutcomeFactory().createOutcome("Straight " + Integer.toString(cnt), betOdds));
        }
        // build straight bets 0 and 37
        wheel.addOutcome(0, OutcomeFactory.getOutcomeFactory().createOutcome("Straight 0", betOdds));
        wheel.addOutcome(37, OutcomeFactory.getOutcomeFactory().createOutcome("Straight 00", betOdds));
    }
    
    /**
     * Adds all the outcomes that are split bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateSplitBets(Wheel wheel, int betOdds) {
        int n;
        Outcome outcome;
        for (int r = 0; r < 12; r++ ) {
            // column 1-2 split
            n = 3*r+1;
            outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Split " + Integer.toString(n) + "-" + Integer.toString(n+1), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+1, outcome);
            // column 2-3 split
            n = 3*r+2;
            outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Split " + Integer.toString(n) + "-" + Integer.toString(n+1), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+1, outcome);
        }
        for (int r = 0; r < 11; r++ ) {
            // first column number
            n = 3*r+1;
            outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Split " + Integer.toString(n) + "-" + Integer.toString(n+3), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+3, outcome);
            // second column number
            n = 3*r+2;
            outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Split " + Integer.toString(n) + "-" + Integer.toString(n+3), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+3, outcome);
            // third column number
            n = 3*r+3;
            outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Split " + Integer.toString(n) + "-" + Integer.toString(n+3), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+3, outcome);
        }
    }
    
    /**
     * Adds all the outcomes that are street bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateStreetBets(Wheel wheel, int betOdds) {
        int n;
        Outcome outcome;
        for (int r = 0; r < 12; r++) {
            n = 3*r+1;
            outcome =   OutcomeFactory.getOutcomeFactory().createOutcome("Street " + Integer.toString(n) + "-" 
                        + Integer.toString(n+1) + "-"
                        + Integer.toString(n+2), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+1, outcome);
            wheel.addOutcome(n+2, outcome);
        }
    }
    
    /**
     * Adds all the outcomes that are corner bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateCornerBets(Wheel wheel, int betOdds) {
        int n;
        Outcome outcome;
        for (int r = 0; r < 11; r++) {
            // first column number
            n = 3*r+1;
            outcome =   OutcomeFactory.getOutcomeFactory().createOutcome("Corner " + Integer.toString(n) + "-" 
                        + Integer.toString(n+1) + "-"
                        + Integer.toString(n+3) + "-"
                        + Integer.toString(n+4), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+1, outcome);
            wheel.addOutcome(n+3, outcome);
            wheel.addOutcome(n+4, outcome);
            // second column number
            n = 3*r+2;
            outcome =   OutcomeFactory.getOutcomeFactory().createOutcome("Corner " + Integer.toString(n) + "-" 
                        + Integer.toString(n+1) + "-"
                        + Integer.toString(n+3) + "-"
                        + Integer.toString(n+4), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+1, outcome);
            wheel.addOutcome(n+3, outcome);
            wheel.addOutcome(n+4, outcome);
        }
    }
    
    /**
     * Adds all the outcomes that are line bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateLineBets(Wheel wheel, int betOdds) {
        int n;
        Outcome outcome;
        for (int r = 0; r < 10; r++) {
            n = 3*r+1;
            outcome =   OutcomeFactory.getOutcomeFactory().createOutcome("Line " + Integer.toString(n) + "-" 
                        + Integer.toString(n+1) + "-"
                        + Integer.toString(n+2) + "-"
                        + Integer.toString(n+3) + "-"
                        + Integer.toString(n+4) + "-"
                        + Integer.toString(n+5), betOdds);
            wheel.addOutcome(n, outcome);
            wheel.addOutcome(n+1, outcome);
            wheel.addOutcome(n+2, outcome);
            wheel.addOutcome(n+3, outcome);
            wheel.addOutcome(n+4, outcome);
            wheel.addOutcome(n+5, outcome);
        }
    }
    
    /**
     * Adds all the outcomes that are dozen bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateDozenBets(Wheel wheel, int betOdds) {
        Outcome outcome;
        for (int d = 0; d < 3; d++) { // iterate through each dozen
            outcome =   OutcomeFactory.getOutcomeFactory().createOutcome("Dozen " + Integer.toString(12*d+1) + " to " 
                        + Integer.toString(12*d+12), betOdds);
            for (int m = 0; m < 12; m++) { // iterate through each bin within the current dozen
                wheel.addOutcome(12*d+m+1, outcome);
            }
        }  
    }
    
    /**
     * Adds all the outcomes that are column bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateColumnBets(Wheel wheel, int betOdds) {
        Outcome outcome;
        for (int c = 0; c < 3; c++) { // iterate through each column
            outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Column " + Integer.toString(c+1), betOdds);
            for (int r = 0; r < 12; r++) { // iterate through each bin within the current column
                wheel.addOutcome(3*r+c+1, outcome);
            }
        }
    }
    
    /**
     * Adds all the outcomes that are even-money bets to the appropriate bins in
     * the wheel.
     * 
     * @param wheel             outcomes will be added to the bins of this wheel
     * @param rouletteGame      the game controller
     * @param outcomeFactory    factory to be used to create outcomes
     */
    private static void generateEvenMoneyBets(Wheel wheel, int betOdds) {
        Outcome redOutcome = OutcomeFactory.getOutcomeFactory().createOutcome("Red", betOdds);
        Outcome blackOutcome = OutcomeFactory.getOutcomeFactory().createOutcome("Black", betOdds);
        Outcome evenOutcome = OutcomeFactory.getOutcomeFactory().createOutcome("Even", betOdds);
        Outcome oddOutcome = OutcomeFactory.getOutcomeFactory().createOutcome("Odd", betOdds);
        Outcome highOutcome = OutcomeFactory.getOutcomeFactory().createOutcome("High", betOdds);
        Outcome lowOutcome = OutcomeFactory.getOutcomeFactory().createOutcome("Low", betOdds);
        
        int[] redArray = {1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 30, 32};
        
        for (int n = 1; n < 37; n++) {
            // low or high?
            if (1 <= n && n < 19)
                wheel.addOutcome(n, lowOutcome);
            else
                wheel.addOutcome(n, highOutcome);
            // even or odd?
            if (n%2 == 0)
                wheel.addOutcome(n, evenOutcome);
            else
                wheel.addOutcome(n, oddOutcome);
            // red or black?
            if (Arrays.binarySearch(redArray, n) >= 0)
                wheel.addOutcome(n, redOutcome);
            else
                wheel.addOutcome(n, blackOutcome);
        }
    }
    
    private static void generateFiverBets(Wheel wheel, int betOdds) {
        Outcome outcome = OutcomeFactory.getOutcomeFactory().createOutcome("Fiver", betOdds);
        wheel.addOutcome(0, outcome);
        wheel.addOutcome(1, outcome);
        wheel.addOutcome(2, outcome);
        wheel.addOutcome(3, outcome);
        wheel.addOutcome(37, outcome);
    }
}
